<!DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>前端上手 | LinCMS-TP5入门</title>
    <meta name="generator" content="VuePress 1.5.0">
    
    <meta name="description" content="基于ThinkPHP 5.1的 Lin CMS 后端实现。">
    <link rel="preload" href="/lin-cms-book/assets/css/0.styles.e8c0fe6e.css" as="style"><link rel="preload" href="/lin-cms-book/assets/js/app.43f3ff7b.js" as="script"><link rel="preload" href="/lin-cms-book/assets/js/2.1c264783.js" as="script"><link rel="preload" href="/lin-cms-book/assets/js/11.5fc2ad3e.js" as="script"><link rel="prefetch" href="/lin-cms-book/assets/js/10.b29049a1.js"><link rel="prefetch" href="/lin-cms-book/assets/js/12.0fb72fc4.js"><link rel="prefetch" href="/lin-cms-book/assets/js/3.12364cb0.js"><link rel="prefetch" href="/lin-cms-book/assets/js/4.606d0aff.js"><link rel="prefetch" href="/lin-cms-book/assets/js/5.7bb207a9.js"><link rel="prefetch" href="/lin-cms-book/assets/js/6.1906fec0.js"><link rel="prefetch" href="/lin-cms-book/assets/js/7.2d983749.js"><link rel="prefetch" href="/lin-cms-book/assets/js/8.03718c42.js"><link rel="prefetch" href="/lin-cms-book/assets/js/9.2e1a8f4e.js">
    <link rel="stylesheet" href="/lin-cms-book/assets/css/0.styles.e8c0fe6e.css">
  </head>
  <body>
    <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/lin-cms-book/" class="home-link router-link-active"><!----> <span class="site-name">LinCMS-TP5入门</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/lin-cms-book/" class="nav-link">
  简介
</a></div><div class="nav-item"><a href="/lin-cms-book/start/server_deploy.html" class="nav-link">
  入门
</a></div><div class="nav-item"><a href="/lin-cms-book/dev/" class="nav-link">
  开发文档
</a></div><div class="nav-item"><a href="/lin-cms-book/log/" class="nav-link">
  版本日志
</a></div><div class="nav-item"><a href="/lin-cms-book/qa/" class="nav-link">
  常见问题
</a></div><div class="nav-item"><a href="http://doc.cms.7yue.pro/" target="_blank" rel="noopener noreferrer" class="nav-link external">
  林间有风
  <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></div><div class="nav-item"><a href="https://github.com/ChenJinchuang/lin-cms-tp5" target="_blank" rel="noopener noreferrer" class="nav-link external">
  GitHub
  <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></div> <!----></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/lin-cms-book/" class="nav-link">
  简介
</a></div><div class="nav-item"><a href="/lin-cms-book/start/server_deploy.html" class="nav-link">
  入门
</a></div><div class="nav-item"><a href="/lin-cms-book/dev/" class="nav-link">
  开发文档
</a></div><div class="nav-item"><a href="/lin-cms-book/log/" class="nav-link">
  版本日志
</a></div><div class="nav-item"><a href="/lin-cms-book/qa/" class="nav-link">
  常见问题
</a></div><div class="nav-item"><a href="http://doc.cms.7yue.pro/" target="_blank" rel="noopener noreferrer" class="nav-link external">
  林间有风
  <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></div><div class="nav-item"><a href="https://github.com/ChenJinchuang/lin-cms-tp5" target="_blank" rel="noopener noreferrer" class="nav-link external">
  GitHub
  <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></div> <!----></nav>  <ul class="sidebar-links"><li><a href="/lin-cms-book/start/server_deploy.html" class="sidebar-link">后端起步</a></li><li><a href="/lin-cms-book/start/vue_deploy.html" class="sidebar-link">前端起步</a></li><li><a href="/lin-cms-book/start/server_demo.html" class="sidebar-link">后端上手</a></li><li><a href="/lin-cms-book/start/vue_demo.html" aria-current="page" class="active sidebar-link">前端上手</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/lin-cms-book/start/vue_demo.html#建立页面" class="sidebar-link">建立页面</a></li><li class="sidebar-sub-header"><a href="/lin-cms-book/start/vue_demo.html#页面路由" class="sidebar-link">页面路由</a></li><li class="sidebar-sub-header"><a href="/lin-cms-book/start/vue_demo.html#获取数据" class="sidebar-link">获取数据</a></li><li class="sidebar-sub-header"><a href="/lin-cms-book/start/vue_demo.html#异常处理" class="sidebar-link">异常处理</a></li><li class="sidebar-sub-header"><a href="/lin-cms-book/start/vue_demo.html#权限控制" class="sidebar-link">权限控制</a></li></ul></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="前端上手"><a href="#前端上手" class="header-anchor">#</a> 前端上手</h1> <blockquote><p><strong>WARNING</strong><br>
阅读本小节前，请确保你已经完成了后端快速上手，根据已经完成的 API 来完成前端页面。<br>
本小节主要目的：让刚接触 lin-cms 的同学，通过这样一个简单的例子，初步了解 lin-cms 的运行机制，比较熟悉的同学可跳过。</p></blockquote> <p>想要完成这样一个图书管理 demo，需要以下流程：</p> <ul><li>新建承载内容的页面文件</li> <li>配置访问页面需要的路由</li> <li>通过 API 将数据渲染到页面</li> <li>通过 API 完成添加、删除等用户行为</li> <li>遇到 API 异常及时进行处理</li></ul> <table><thead><tr><th>url</th> <th>description</th> <th>method</th></tr></thead> <tbody><tr><td>/v1/book/:id</td> <td>查询指定 id 的书籍</td> <td>GET</td></tr> <tr><td>/v1/book/:id</td> <td>更新指定 id 的书籍</td> <td>PUT</td></tr> <tr><td>/v1/book/:id</td> <td>删除指定 id 的书籍</td> <td>DELETE</td></tr> <tr><td>/v1/book/:id</td> <td>创建图书</td> <td>POST</td></tr> <tr><td>/v1/book/:id</td> <td>获取所有图书</td> <td>GET</td></tr></tbody></table> <h2 id="建立页面"><a href="#建立页面" class="header-anchor">#</a> 建立页面</h2> <p>从业务逻辑分析，图书管理需要有图书列表与添加图书两个页面，先新建<code>BookAdd.vue和BookList.vue</code>两个文件。</p> <p>位置：<code>src/views/book/</code></p> <p>PS: 如果对Lin的目录结构不是非常清楚，可以先进行大致浏览。</p> <p><img src="https://consumerminiaclprd01.blob.core.chinacloudapi.cn/miniappbackground/sfgmember/lin/docs/book.png" alt="GitHub"></p> <h2 id="页面路由"><a href="#页面路由" class="header-anchor">#</a> 页面路由</h2> <p>页面想要被访问需要有对应路由，接下来完成图书管理的路由配置：</p> <p>位置： <code>src/config/stage/book.js</code></p> <div class="language-js line-numbers-mode"><pre class="language-js"><code><span class="token keyword">const</span> bookRouter <span class="token operator">=</span> <span class="token punctuation">{</span>
  route<span class="token operator">:</span> <span class="token keyword">null</span><span class="token punctuation">,</span>
  name<span class="token operator">:</span> <span class="token keyword">null</span><span class="token punctuation">,</span>
  title<span class="token operator">:</span> <span class="token string">'图书管理'</span><span class="token punctuation">,</span>
  type<span class="token operator">:</span> <span class="token string">'folder'</span><span class="token punctuation">,</span> <span class="token comment">// 类型: folder, tab, view</span>
  icon<span class="token operator">:</span> <span class="token string">'iconfont icon-demo'</span><span class="token punctuation">,</span>
  filePath<span class="token operator">:</span> <span class="token string">'views/book/'</span><span class="token punctuation">,</span> <span class="token comment">// 文件路径</span>
  order<span class="token operator">:</span> <span class="token keyword">null</span><span class="token punctuation">,</span>
  inNav<span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
  children<span class="token operator">:</span> <span class="token punctuation">[</span>
    <span class="token punctuation">{</span>
      title<span class="token operator">:</span> <span class="token string">'添加图书'</span><span class="token punctuation">,</span>
      type<span class="token operator">:</span> <span class="token string">'view'</span><span class="token punctuation">,</span>
      name<span class="token operator">:</span> <span class="token string">'bookAdd'</span><span class="token punctuation">,</span>
      route<span class="token operator">:</span> <span class="token string">'/book/add'</span><span class="token punctuation">,</span>
      filePath<span class="token operator">:</span> <span class="token string">'views/book/BookAdd.vue'</span><span class="token punctuation">,</span>
      inNav<span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
      icon<span class="token operator">:</span> <span class="token string">'iconfont icon-demo'</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">{</span>
      title<span class="token operator">:</span> <span class="token string">'图书列表'</span><span class="token punctuation">,</span>
      type<span class="token operator">:</span> <span class="token string">'view'</span><span class="token punctuation">,</span>
      name<span class="token operator">:</span> <span class="token string">'bookAdd'</span><span class="token punctuation">,</span>
      route<span class="token operator">:</span> <span class="token string">'/book/list'</span><span class="token punctuation">,</span>
      filePath<span class="token operator">:</span> <span class="token string">'views/book/BookList.vue'</span><span class="token punctuation">,</span>
      inNav<span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">]</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span>

<span class="token keyword">export</span> <span class="token keyword">default</span> bookRouter
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br></div></div><p>此时，我们只是把图书管理的路由文件建立，接下来需要将数据插入到整个路由树中：</p> <p>位置： <code>src/config/stage/index.js</code></p> <p><img src="https://consumerminiaclprd01.blob.core.chinacloudapi.cn/miniappbackground/sfgmember/lin/docs/book10.png" alt="GitHub"></p> <p>到这里，已经可以看到图书管理的菜单和页面了。</p> <p><img src="https://consumerminiaclprd01.blob.core.chinacloudapi.cn/miniappbackground/sfgmember/lin/docs/book8.png" alt="GitHub"></p> <h2 id="获取数据"><a href="#获取数据" class="header-anchor">#</a> 获取数据</h2> <p>图书列表页面，需要先从 API 获取到数据，并将其渲染到视图中。首选调用查询 API 接口：</p> <p>位置：<code>src/views/book/BookList.vue</code></p> <div class="language-js line-numbers-mode"><pre class="language-js"><code><span class="token operator">&lt;</span>script<span class="token operator">&gt;</span>
<span class="token keyword">import</span> book <span class="token keyword">from</span> <span class="token string">'@/lin/models/book'</span>

<span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token punctuation">{</span>
  <span class="token function">data</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token punctuation">{</span>
      tableColumn<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">{</span> prop<span class="token operator">:</span> <span class="token string">'title'</span><span class="token punctuation">,</span> label<span class="token operator">:</span> <span class="token string">'书名'</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> prop<span class="token operator">:</span> <span class="token string">'author'</span><span class="token punctuation">,</span> label<span class="token operator">:</span> <span class="token string">'作者'</span> <span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
      tableData<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
      operate<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
   <span class="token keyword">async</span> <span class="token function">created</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>loading <span class="token operator">=</span> <span class="token boolean">true</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">getBooks</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>loading <span class="token operator">=</span> <span class="token boolean">false</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  methods<span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token keyword">async</span> <span class="token function">getBooks</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token keyword">const</span> books <span class="token operator">=</span> <span class="token keyword">await</span> book<span class="token punctuation">.</span><span class="token function">getBooks</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
      <span class="token keyword">this</span><span class="token punctuation">.</span>tableData <span class="token operator">=</span> books
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token operator">&lt;</span><span class="token operator">/</span>script<span class="token operator">&gt;</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br></div></div><p>那么根据在<code>模型层</code>中的介绍，将所有与 API 相关的处理，封装到<code>models</code>下面的一个<code>book.js</code>文件中。</p> <p>位置：<code>src/lin/models/book.js</code></p> <div class="language-js line-numbers-mode"><pre class="language-js"><code><span class="token keyword">import</span> <span class="token punctuation">{</span> <span class="token keyword">get</span> <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'../utils/http'</span>

<span class="token comment">// 我们通过 class 这样的语法糖使模型这个概念更加具象化，其优点：耦合性低、可维护性。</span>
<span class="token keyword">class</span> <span class="token class-name">Book</span> <span class="token punctuation">{</span>
  <span class="token keyword">async</span> <span class="token function">getBooks</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">const</span> res <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token keyword">get</span><span class="token punctuation">(</span><span class="token string">'v1/book/'</span><span class="token punctuation">)</span>
    <span class="token keyword">return</span> res
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token keyword">new</span> <span class="token class-name">Book</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br></div></div><p>这样通过数据的变更来改变视图，图书列表就可以渲染出来了：</p> <p><img src="https://consumerminiaclprd01.blob.core.chinacloudapi.cn/miniappbackground/sfgmember/lin/docs/book9.png" alt="GitHub"></p> <h2 id="异常处理"><a href="#异常处理" class="header-anchor">#</a> 异常处理</h2> <p>如果在数据获取过程中，遇到异常情况，根据在<code>异常机制</code>的介绍，通过 API 返回的不同 <code>error_code</code> 将异常拦截在 <code>src/lin/utils/exception.js</code> 这个文件中进行处理，这里就不详细说明了。</p> <h2 id="权限控制"><a href="#权限控制" class="header-anchor">#</a> 权限控制</h2> <p>权限的控制有两种：</p> <ul><li>视图层的访问权限，也就是菜单根据权限来显示</li> <li>API 的操作权限</li></ul> <p>具体<code>权限控制</code>请参考专门的章节介绍</p></div> <footer class="page-edit"><!----> <div class="last-updated"><span class="prefix">最后更新时间:</span> <span class="time">5/26/2020, 10:51:39 PM</span></div></footer> <div class="page-nav"><p class="inner"><span class="prev">
      ←
      <a href="/lin-cms-book/start/server_demo.html" class="prev">
        后端上手
      </a></span> <!----></p></div> </main></div><div class="global-ui"></div></div>
    <script src="/lin-cms-book/assets/js/app.43f3ff7b.js" defer></script><script src="/lin-cms-book/assets/js/2.1c264783.js" defer></script><script src="/lin-cms-book/assets/js/11.5fc2ad3e.js" defer></script>
  </body>
</html>
